#include <iostream>
#include <string>

#include <boost/swap.hpp>
#include <boost/move/adl_move_swap.hpp>

namespace other {
	class characteristics {};
}

struct person_info {
	bool is_male_;
	std::string name_;
	std::string second_name_;
	other::characteristics characteristics_;

	void swap(person_info& rhs) {
		std::swap(is_male_, rhs.is_male_);
		name_.swap(rhs.name_);
		second_name_.swap(rhs.second_name_);
		boost::swap(characteristics_, rhs.characteristics_);
	}

private:
	BOOST_COPYABLE_AND_MOVABLE(person_info);

public:
	person_info() {}

	person_info(const person_info& p)
		: is_male_(p.is_male_)
		, name_(p.name_)
		, second_name_(p.second_name_)
		, characteristics_(p.characteristics_)
	{}

	person_info& operator=(BOOST_RV_REF(person_info) person) {
		if (this != &person) {
			swap(person);
			person_info tmp;
			tmp.swap(person);
		}
		return *this;
	}
};

int main()
{
	person_info vasya;
	vasya.name_ = "Vasya";
	vasya.second_name_ = "Snow";
	vasya.is_male_ = true;

	person_info new_vasya(boost::move(vasya));
	std::cout << "==== 1 ====" << std::endl;
	std::cout << "new_vasya.name_:" << new_vasya.name_ << "   "
		<< "new_vasya.second_name_:" << new_vasya.second_name_ << "   "
		<< "vasya.name_:" << vasya.name_ << "   "
		<< "vasya.second_name_:" << vasya.second_name_ << "   "
		<< std::boolalpha
		<< "vasya.name_.empty():" << vasya.name_.empty() << "   "
		<< "vasya.second_name_.empty():" << vasya.second_name_.empty() << "   "
		<< std::endl;

	vasya = boost::move(new_vasya);
	std::cout << "==== 2 ====" << std::endl;
	std::cout << "vasya.name_:" << vasya.name_ << "   "
		<< "vasya.second_name_:" << vasya.second_name_ << "   "
		<< "new_vasya.name_:" << new_vasya.name_ << "   "
		<< "new_vasya.second_name_:" << new_vasya.second_name_ << "   "
		<< std::boolalpha
		<< "new_vasya.name_.empty():" << new_vasya.name_.empty() << "   "
		<< "new_vasya.second_name_.empty():" << new_vasya.second_name_.empty() << "   "
		<< std::endl;

	return 0;
}